package nautilus.tank.component;

import java.awt.Canvas;
import java.awt.Color;
import java.awt.RenderingHints;
import java.awt.Dimension;
import java.awt.GradientPaint;
import java.awt.Graphics2D;
import java.awt.Paint;
import java.awt.Toolkit;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.geom.AffineTransform;
import java.awt.image.BufferStrategy;
import java.util.Timer;
import java.util.TimerTask;

import nautilus.tank.Constant;
import nautilus.tank.model.ActionOrder;
import nautilus.tank.model.BattleObject;
import nautilus.tank.model.Game;
import nautilus.tank.model.IBattleObject;
import nautilus.tank.model.IVehicleWeapon;
import nautilus.tank.model.Player;

public class MapCanvas extends Canvas{
	private Game game;
	
	private BufferStrategy		strategy;
	private final Timer			timer;
	private TimerTask			renderTask;
	private Paint				backgroundGradient;
	private AffineTransform transform = new AffineTransform();
	
	public MapCanvas(){
		setIgnoreRepaint(true);
		timer = new Timer();
		initListeners();
		setPreferredSize(new Dimension(700, 450));
		game = new Game();
	}
	
	private void render(){
		Graphics2D g2 = (Graphics2D)strategy.getDrawGraphics();
		g2.setPaint(backgroundGradient);
		g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,  
                            RenderingHints.VALUE_ANTIALIAS_ON);
		//g2.fillRect(0, 0, getWidth(), getHeight());
		
		//TODO: draw frame here
		//1. draw map
		game.renderMap(g2);
		//2. draw static objects
		//3. draw moving objects
		for(IVehicleWeapon vehicle: game.getPlayes().get(0).getVehicles())
			vehicle.draw(g2, transform);
		
		//Release resources
		g2.dispose();
		
		//copy from buffer to component
		strategy.show();
		
		//Synchronize with the display refresh rate
		Toolkit.getDefaultToolkit().sync();	
	}
	
	private void start(){
		if(renderTask != null)
			renderTask.cancel();
			
		renderTask = new TimerTask(){
			long lastTime = System.currentTimeMillis();
			
			@Override
			public void run(){
				long ctime = System.currentTimeMillis();
				double dt = (ctime - lastTime) * 0.001;
				lastTime = ctime;
				render();
			}
		};
		
		timer.schedule(renderTask, 0, Constant.FDT);
	}
	
	public void stop(){
		renderTask.cancel();
	}
	
	public void setup(){
		backgroundGradient = new GradientPaint(0, 0, Color.gray, getWidth(),
				getHeight(), Color.lightGray.brighter());
		
		//I use two buffers here, this mean double bufferred
		this.createBufferStrategy(2);
		
		strategy = this.getBufferStrategy();
		
		start();
	}
	
	private void initListeners(){
		addMouseListener(new MouseListener(){
			@Override
			public void mouseClicked(MouseEvent evt) {
				
				if(evt.getButton() == MouseEvent.BUTTON1){
					for(IBattleObject obj: game.getObjects())
						if(obj.isInsideShape(evt.getX(), evt.getY())){
							//vehicle.setSelected(true);
							game.setSelectedObject(obj);
						}
				}else if(evt.getButton() == MouseEvent.BUTTON3){
					IBattleObject obj = game.getSelectedObject();
					if(obj != null){
						ActionOrder ao = new ActionOrder();
						ao.setX(evt.getX());
						ao.setY(evt.getY());
						ao.setKind(ActionOrder.MOVE_BACKWARD);
						obj.onActionOrder(ao);
					}
				}
				System.out.println("[DEBUG] Mouse clicked " + evt.getButton());
			}

			@Override
			public void mouseEntered(MouseEvent arg0) {
				// TODO Auto-generated method stub
				
			}

			@Override
			public void mouseExited(MouseEvent arg0) {
				// TODO Auto-generated method stub
				
			}

			@Override
			public void mousePressed(MouseEvent arg0) {
				// TODO Auto-generated method stub
				
			}

			@Override
			public void mouseReleased(MouseEvent arg0) {
				// TODO Auto-generated method stub
				
			}
		});
	}
}
